using System;
using System.Collections.Generic;
using System.Text;

namespace csammisrun.MsnLib
{
  public enum UserListType
  {
    Forward,
    Reverse,
    Block,
    Allow
  }

  public class UserList : IDisposable
  {
    /// <summary>
    /// Returns the <see cref="UserListType"/> corresponding to an MSN list acronym
    /// </summary>
    public static UserListType GetListTypeByName(string name)
    {
      switch (name.ToLower()[0])
      {
        case 'r': return UserListType.Reverse;
        case 'b': return UserListType.Block;
        case 'a': return UserListType.Allow;
        case 'f': return UserListType.Forward;
      }
      throw new ArgumentException(String.Format("{0} is not a valid MSN list acronym", name));
    }

    /// <summary>
    /// Returns the MSN list acronym corresponding to a <see cref="UserListType"/>
    /// </summary>
    public static string GetListNameByType(UserListType type)
    {
      switch (type)
      {
        case UserListType.Allow: return "AL";
        case UserListType.Block: return "BL";
        case UserListType.Reverse: return "RL";
        case UserListType.Forward: return "FL";
      }
      throw new ArgumentException("Apparently the UserListType enumeration grew an extra member");
    }

    private UserListType _type = UserListType.Forward;
    private List<User> _users = new List<User>();
    private List<Group> _groups = new List<Group>();
    private Queue<User> _iconrequests = new Queue<User>();
    int _iconwindow = 1;

    #region Location methods
    /// <summary>
    /// Gets a <see cref="User"/> by its Passport id
    /// </summary>
    /// <returns>A user with the requested Passport, or null if one does not exist in this list</returns>
    public User FindUserByPassport(string passport)
    {
      foreach (User user in _users)
      {
        if (user.Passport == passport)
        {
          return user;
        }
      }
      return null;
    }

    /// <summary>
    /// Gets a <see cref="Group"/> by its ID
    /// </summary>
    /// <returns>A group with the requested ID, or null if one does not exist in this list</returns>
    public Group FindGroupByID(int groupid)
    {
      foreach (Group group in _groups)
      {
        if (group.ID == groupid)
        {
          return group;
        }
      }
      return null;
    }

    /// <summary>
    /// Gets a <see cref="Group"/> by its display name
    /// </summary>
    /// <returns>A group with the requested display name, or null if one does not exist in this list</returns>
    public Group FindGroupByName(string displayname)
    {
      foreach (Group group in _groups)
      {
        if (group.DisplayName == displayname)
        {
          return group;
        }
      }
      return null;
    }
    #endregion

    /// <summary>
    /// Adds a <see cref="User"/> with an initial <see cref="Group"/> to this UserList
    /// </summary>
    /// <returns><c>true</c> if the user was able to be added immediately, <c>false</c> if the group had to be added first</returns>
    /// <remarks>
    /// <para><paramref name="Group"/> can be <c>null</c> if no group is required</para>
    /// <para><paramref name="User"/> must, at a minimum, have its Passport name set</para></remarks>
    public bool AddUser(User user, Group group)
    {
      if (FindUserByPassport(user.Passport) != null)
      {
        throw new ArgumentException(String.Format("User {0} already exists in this UserList",
          user.Passport));
      }

      if (user.ServerName == "")
      {
        user.ServerName = user.Passport;
      }

      if (group != null)
      {
        if (FindGroupByName(group.DisplayName) == null)
        {
          // Add the group to the server
          return false;
        }
      }

      // Add the user
      return true;
    }

    /// <summary>
    /// Remove a <see cref="User"/> from a <see cref="Group"/> contained in a UserList
    /// </summary>
    public void RemoveUser(User user, Group group)
    {
      if (FindUserByPassport(user.Passport) == null)
      {
        throw new ArgumentException(String.Format("User {0} does not exist in this UserList",
          user.Passport));
      }

      // Sanity check, does this user actually belong to this group?
      if (!user.Groups.Contains(group))
      {
        throw new ArgumentException(String.Format("User {0} does not belong to group {1}",
          user.Passport, group.DisplayName));
      }

      // Notify the server of the removal
    }

    #region Properties
    public List<User> Users
    {
      get { return _users; }
    }

    public List<Group> Groups
    {
      get { return _groups; }
    }

    private bool _issyncing = false;
    public bool IsSyncing
    {
      get { return _issyncing; }
      set { _issyncing = value; }
    }
    #endregion

    #region IDisposable Members

    public void Dispose()
    {
    }

    #endregion
  }
}
